package com.gao.config;

import com.gao.handler.JwtLogoutHandler;
import com.gao.web.filter.JwtFilter;
import com.gao.web.filter.TestFilter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author gao
 * @time 2022/11/05 10:30:39
 */
@RequiredArgsConstructor
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @NonNull
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    @NonNull
    private AuthenticationFailureHandler authenticationFailureHandler;

    @NonNull
    private AuthenticationEntryPoint authenticationEntryPoint;
    @NonNull
    private AccessDeniedHandler accessDeniedHandler;

    @NonNull
    private JwtLogoutHandler jwtLogoutHandler;
    @NonNull
    private LogoutSuccessHandler logoutSuccessHandler;

    @NonNull
    private JwtFilter jwtFilter;
    @NonNull
    private TestFilter testFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // 设置只有通过认证才能访问/api/greeting
        http.authorizeRequests()
                .antMatchers("/api/greeting")
                .authenticated();

        // 设置只有用户拥有admin角色才能访问/api/rushb
        http.authorizeRequests()
                .antMatchers("/api/rushb")
                .hasRole("admin");


        // 开启表单认证方式，自定义认证成功和失败的回调
        http.formLogin()
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler);

        // 配置访问资源时没有对应认证和授权的回调
        http.exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler);

        // 禁用会话
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        http.addFilterAfter(testFilter, UsernamePasswordAuthenticationFilter.class);

        // 禁用csrf防御
        http.csrf().disable();



        http
                .logout()
                .logoutUrl("/logout")
                .addLogoutHandler(jwtLogoutHandler)
                .logoutSuccessHandler(logoutSuccessHandler);

    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
